#include <libxml/parser.h>
#include <libxml/xmlschemas.h>

#include <stdio.h>
#include <string.h>
#include <sysexits.h>
#include <syslog.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <ctype.h>

#include <mcx/mcx.h>

#include "common.h"

const char *const sessiontop = "/home/sessions/web/";
const char *const paypaltop = "/home/sessions/paypal/";
const char *const appendread = "/KeyInfo.xml";
const char *const appendlink = "/Authority.xml";
const char *const appendwrite = ".xml";

int main(int argc, char **argv) {
  xmlDocPtr doc, authority;
  char *readfile, *writefile, *linkfile, *ptr;
  xmlNodePtr root, ar;
  xmlSchemaParserCtxtPtr parser;
  xmlSchemaValidCtxtPtr vctx;
  xmlSchemaPtr schemap;
#if 0
  xmlNsPtr dosh, xsi;
  char *tmp;
  xmlNodePtr e;
#endif  
  int fd;
  FILE *f;
  
  if(clearenv()) {
    syslog(LOG_WARNING, "clearenv failed");
    exit(EX_SOFTWARE);
  }
  openlog("validate-keyinfo", LOG_PID|LOG_PERROR, LOG_AUTHPRIV);
  if(argc != 4) {
    syslog(LOG_WARNING, "called with argc == %d, invalid", argc);
    exit(EX_USAGE);
  }
  for(ptr = argv[1]; *ptr; ptr++)
    if(!isxdigit(*ptr)) {
      syslog(LOG_WARNING, "invalid character in filename");
      exit(EX_USAGE);
    }
  for(ptr = argv[2]; *ptr; ptr++)
    if(!isalnum(*ptr)) {
      syslog(LOG_WARNING, "invalid character in filename");
      exit(EX_USAGE);
    }
  for(ptr = argv[3]; *ptr; ptr++)
    if(!isupper(*ptr)) {
      syslog(LOG_WARNING, "invalid character in currency");
      exit(EX_USAGE);
    }

  readfile = alloca(strlen(sessiontop) + strlen(argv[1]) + strlen(appendread) + 1);
  strcpy(readfile, sessiontop);
  strcat(readfile, argv[1]);
  strcat(readfile, appendread);

  writefile = alloca(strlen(paypaltop) + strlen(argv[2]) + strlen(appendwrite) + 1);
  strcpy(writefile, paypaltop);
  strcat(writefile, argv[2]);
  strcat(writefile, appendwrite);

  linkfile = alloca(strlen(sessiontop) + strlen(argv[1]) + strlen(appendlink) + 1);
  strcpy(linkfile, sessiontop);
  strcat(linkfile, argv[1]);
  strcat(linkfile, appendlink);

  libSetup();
  doc = xmlParseFile(readfile);
  if(!doc) {
    syslog(LOG_WARNING, "Not parseable as XML");
    exit(EX_DATAERR);
  }
  root = xmlDocGetRootElement(doc);
  if(!root) {
    syslog(LOG_WARNING, "No root element in document");
    exit(EX_DATAERR);
  }

  parser = xmlSchemaNewParserCtxt("/home/xml/xmldsig-core-schema.xsd");
  if(!parser) {
    syslog(LOG_WARNING, "Couldn't load schema to validate document");
    exit(EX_DATAERR);
  }

  schemap = xmlSchemaParse(parser);
  if(!parser) {
    syslog(LOG_WARNING, "Couldn't parse schema");
    exit(EX_DATAERR);
  }

  vctx = xmlSchemaNewValidCtxt(schemap);
  if(!vctx) {
    syslog(LOG_WARNING, "Couldn't create validation context");
    exit(EX_DATAERR);
  }

  if(xmlSchemaValidateDoc(vctx, doc)) {
    syslog(LOG_WARNING, "Document failed to validate");
    exit(EX_DATAERR);
  }

  fd = open(writefile, O_CREAT|O_EXCL|O_WRONLY, 0644);
  if(fd < 0) {
    syslog(LOG_WARNING, "Failed to create writefile");
    exit(EX_SOFTWARE);
  }
  
#if 0
  authority = xmlNewDoc("1.0");
  ar = xmlNewDocNode(authority, NULL, "authority", NULL);
  dosh = xmlNewNs(ar, "urn:dosh", "dosh");
  /* xsi = xmlNewNs(ar, "http://www.w3.org/2001/XMLSchema-instance", "xsi"); */
  xmlSetNs(ar, dosh);
  /*
  xmlNewNsProp(ar, xsi, "schemaLocation", "urn:frog file:///home/dichro/.c/house/xsd.xml urn:doshwsdl file:///home/dichro/.c/house/settlement-ws.xsd");
  */
  xmlDocSetRootElement(authority, ar);
  /* recipient */
  e = xmlNewDocNode(authority, dosh, "recipient", NULL);
  xmlAddChild(e, xmlDocCopyNode(root, authority, 1));
  xmlAddChild(ar, e);
  /* amount */
  e = xmlNewDocNode(authority, dosh, "amount", "5.00");
  xmlSetProp(e, "currency", argv[3]);
  xmlAddChild(ar, e);
  /* validityInterval */
  e = xmlNewDocNode(authority, dosh, "validityInterval", NULL);
  tmp = makeTime(time(NULL));
  tmp[strlen(tmp) - 6] = 'Z';
  tmp[strlen(tmp) - 5] = 0;
  xmlAddChild(e, xmlNewDocNode(authority, dosh, "notBefore", tmp));
  tmp = makeTime(time(NULL) + 7 * 86400);
  tmp[strlen(tmp) - 6] = 'Z';
  tmp[strlen(tmp) - 5] = 0;
  xmlAddChild(e, xmlNewDocNode(authority, dosh, "notAfter", tmp));
  xmlAddChild(ar, e);
  /* signature */
#else
  authority = mcx_authority(root, argv[3], "5.00");
  ar = xmlDocGetRootElement(authority);
#endif
  sign("/home/sessions/generate/signature-authority.xml", ar);
  

  f = fdopen(fd, "w");
  xmlDocDump(f, authority);
  fclose(f);
  close(fd);

  if(link(writefile, linkfile)) {
    syslog(LOG_WARNING, "Failed to link writefile to linkfile");
    exit(EX_SOFTWARE);
  }
  return 0;
}

